/*
 * 1、OOP : Object Oriented Programming , 面向对象编程
 * 2、面向对象编程三个基本特征: 
 *      封装(encapsulation)
 *      继承(Inheritance)
 *      多态(polymorphism)
 * 3、封装(encapsulation)
 *      理解概念: 什么是封装?
 *          白话:　封装就是把该藏的藏起来，把该露的露出来
 *      知道作用: 封装所有什么用?
 *          用封装可以将数据和实现细节隐藏起来，同时对外暴露可以访问这些隐藏变量和函数的方法
 *      能够应用: 能够使用封装技术
 *          数据和实现细节的隐藏可以通过 构造函数的 局部变量 和 内部函数 来实现
 */

// 定义圆对象
function Circle(r){
    // 在构造函数内部可以通过定义"局部变量"来实现 私有变量( private variable )
    const PI = 3.1415926 ;
    // 若 r 为 undefined 、null 、0 、'' 、NaN 则 r 都可以表示 false
    let radius = r || 0 ; // 若 r 为 true 则不执行 || 之后的表达式；若 r 为 false 则执行 ||之后的表达式
    console.log( PI , radius );

    // 在构造函数内部可以通过定义"内部函数"来实现 私有方法( private method )
    function statistics(){
        // 在"内部函数"中可以访问"外部函数"中声明的局部变量 ( 即前面所谓的私有变量 )
        let area = PI * ( radius ** 2 ); // 计算圆面积
        return area ; // 返回圆面积
    }

    // 特权方法( privileged method )可以访问 私有变量 和 私有方法
    this.acreage = function(){
        let area = statistics(); // 调用 私有函数 来计算圆面积
        console.log( `半径为${radius}的圆面积为${area}` ); // 输出 私有变量 (输出不是目的)
        return area ;
    }
}


let x = new Circle(15);
// 通过实例无法访问构造函数内的局部变量
// console.log(x.PI , x.radius ); // undefined undefined
// x.statistics(); // TypeError: x.statistics is not a function

let acreage = x.acreage();
console.log( 'acreage: ' , acreage );
